#include "joystick.h"

#include "application/game_application.h"

#ifdef _PLATFORM_WIN32
#include "application/window_handler_win32.h"
#endif //#ifdef _PLATFORM_WIN32

#include "util/timer.h"				// log
#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"

#include "../sleipner_config.h"

extern "C"
{
    
#ifdef _SDL2
    #include "SDL2/src/joystick/SDL_joystick_c.h"
    #include "SDL2/src/joystick/SDL_sysjoystick.h"
#else
    #include "SDL-1.2.13/src/joystick/SDL_joystick_c.h"
    #include "SDL-1.2.13/src/joystick/SDL_sysjoystick.h"
#endif
}

#include <cassert>
using namespace input;

// http://www.libsdl.org/docs/html/guideinput.html
Joystick& Joystick::Instance()
{
	static Joystick	Inst;
	return Inst;
}

Joystick::Joystick() :	m_pJoystick(NULL),
                m_EventRecived(false)
{
#if defined( _PLATFORM_IOS) || defined(_PLATFORM_ANDROID)

int Status =    SDL_JoystickInit();
#endif
	
}

Joystick::~Joystick()
{
#if defined( _PLATFORM_IOS) || defined(_PLATFORM_ANDROID)
SDL_JoystickQuit();
#endif
}

void		Joystick::JoystickEnable()
{
	if(!m_pJoystick)
	{
		SDL_JoystickEventState(SDL_ENABLE);	
		m_pJoystick = SDL_JoystickOpen(0);
        m_EventRecived = false;
	}
    
	
}

void		Joystick::JoystickDisable()
{
	if(m_pJoystick)
	{
		SDL_JoystickEventState(SDL_DISABLE);	
		SDL_JoystickClose(m_pJoystick);
        m_pJoystick = NULL;
        m_EventRecived = false;
	}	
}

void		Joystick::OnTilt(int Axis,float Value)
{
	//if(Value == 0)
	//	return;
	
	// calculate minimal change?
	if(Axis == AXIS_X)
		m_AxisState.x = Value;
	else if(Axis == AXIS_Y)
		m_AxisState.y = Value;
	else if(Axis == AXIS_X)
		m_AxisState.z = Value;
    
    m_EventRecived = true;
	
    
}

bool Joystick::Tick(float dt)
{
    
	if(m_pJoystick)
	{
        
        if(m_EventRecived)
        {
            // notify tilt 
            size_t Count = m_Listeners.size();
            for (size_t j = 0; j<Count; j++)
            {
                if (m_Listeners[j] && m_Listeners[j]->IsEnabled())
                    m_Listeners[j]->OnJoystickTilt(m_AxisState);
            }
           
			//m_AxisState.x = m_AxisState.y = m_AxisState.z = 0; // reset it
			m_EventRecived = false;
        }
        
	}
	else
	{
		return false;
	}
	
    
	return true;
}


/// Listener stuff... should really be abstracted into an AbstractInput
void	Joystick::AddListener(JoystickListener* _pListener)
{
	assert(_pListener && "Adding illegal listener!");
	// exists already
	int	Index = GetListenerIndex(_pListener);
	if (Index != -1)
		return;
    
	// PIERRE: NULL it, the listener calling check for NULL, AddListener look for a NULL slot first
	for (size_t i = 0; i < m_Listeners.size(); ++i) {
		if (!m_Listeners[i]) {
			// free slot use it
			m_Listeners[i] = _pListener;
			return;
		}
	}
    
	// no free slots add one
	m_Listeners.push_back(_pListener);
}

void	Joystick::DropListener(JoystickListener* _pListener)
{
	// exists already ?
	int	Index = GetListenerIndex(_pListener);
	if (Index == -1)
		return;
    
	// found it.. drop it
    
	// PIERRE: NULL it, the listener calling check for NULL, AddListener look for a NULL slot first
	m_Listeners[Index] = NULL;
    
	//m_Listeners.erase(m_Listeners.begin( ) + Index);
}



int		Joystick::GetListenerIndex(JoystickListener* _pListener)
{
	size_t Size = m_Listeners.size();
	for (size_t i = 0; i<Size; i++)
	{
		if (m_Listeners[i] == _pListener)
			return (int)i;
	}	
	// not found
	return -1;
}

JoystickListener::JoystickListener() :
m_IsEnabled(true)
{
	m_pJoystick = &GET_JOYSTICK();
	if (m_pJoystick )
		m_pJoystick->AddListener(this);
	
}

JoystickListener::~JoystickListener()
{
	m_pJoystick = &GET_JOYSTICK();
	if (m_pJoystick )
		m_pJoystick->DropListener(this);
}




